package com.iwhalecloud.bss.kite.cucc.service.oss;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.cucc.client.api.oss.IAliyunOssService;
import com.iwhalecloud.bss.kite.cucc.client.vo.order.AliyunOssResultVO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Date;
import java.util.List;

@Service
public class AliyunOssService implements IAliyunOssService {

    @Value("${aliyunOss.endpoint}")
    private String endpoint;
    @Value("${aliyunOss.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyunOss.accessKeySecret}")
    private String accessKeySecret;
    @Value("${aliyunOss.bucketName}")
    private String bucketName;
    @Value("${aliyunOss.urlPrefix}")
    private String urlPrefix;


    /**
     * 上传文件，以IO流方式
     *
     * @param inputStream 输入流
     * @param objectName      唯一objectName（在oss中的文件名字）
     */
    @Override
    public AliyunOssResultVO upload(InputStream inputStream, String objectName) {
        AliyunOssResultVO aliyunOssResult = new AliyunOssResultVO();
        try {
            // 创建OSSClient实例。
            ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
            conf.setSLDEnabled(true);
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, conf);
            // 上传内容到指定的存储空间（bucketName）并保存为指定的文件名称（objectName）。
            ossClient.putObject(bucketName, objectName, inputStream);
            // 关闭OSSClient。
            ossClient.shutdown();
            aliyunOssResult.setCode(200);
            aliyunOssResult.setUrl(urlPrefix+objectName);
            aliyunOssResult.setMsg("上传成功");
        } catch (Exception e) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut(e.getMessage());
            aliyunOssResult.setCode(400);
            aliyunOssResult.setMsg("上传失败");
        }
        return aliyunOssResult;
    }

    /**
     * 删除OSS中的单个文件
     *
     * @param objectName 唯一objectName（在oss中的文件名字）
     */
    @Override
    public void delete(String objectName) {
        try {
            // 创建OSSClient实例。
            ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
            conf.setSLDEnabled(true);
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, conf);
            // 删除文件。
            ossClient.deleteObject(bucketName, objectName);
            // 关闭OSSClient。
            ossClient.shutdown();
        } catch (Exception e) {
//            e.printStackTrace();
            ErrorConsts.BUSI_COMMON_ERROR.throwOut(e.getMessage());
        }
    }

    /**
     * 批量删除OSS中的文件
     *
     * @param objectNames oss中文件名list
     */
    @Override
    public void delete(List<String> objectNames) {
        try {
            // 创建OSSClient实例。
            ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
            conf.setSLDEnabled(true);
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, conf);
            // 批量删除文件。
            DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(objectNames));
            List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
            // 关闭OSSClient。
            ossClient.shutdown();
        } catch (Exception e) {
//            e.printStackTrace();
            ErrorConsts.BUSI_COMMON_ERROR.throwOut(e.getMessage());
        }
    }

    /**
     * 获取文件临时url
     *
     * @param objectName oss中的文件名
     * @param effectiveTime 有效时间(ms)
     */
    @Override
    public String getUrl(String objectName, long effectiveTime) {
        // 创建OSSClient实例。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        conf.setSLDEnabled(true);
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, conf);
        // 设置URL过期时间
        Date expiration = new Date(System.currentTimeMillis() + effectiveTime);
        GeneratePresignedUrlRequest generatePresignedUrlRequest ;
        generatePresignedUrlRequest =new GeneratePresignedUrlRequest(bucketName, objectName);
        generatePresignedUrlRequest.setExpiration(expiration);
        URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest);
        return url.toString();
    }

    /**
     * @desc 查看文件列表
     */
    @Override
    public List<OSSObjectSummary> listOSSObjectSummary() {
        // 创建OSSClient实例。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        conf.setSLDEnabled(true);
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, conf);
        // 设置最大个数。
        final int maxKeys = 200;
        // 列举文件。
        ObjectListing objectListing = ossClient.listObjects(new ListObjectsRequest(bucketName).withMaxKeys(maxKeys));
        List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
        return sums;
    }


    /**
     * @desc 下载文件
     */
    @Override
    public void exportOssFileStream(OutputStream os, String objectName) throws IOException {
        // 创建OSSClient实例。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        conf.setSLDEnabled(true);
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, conf);
        boolean isExist = ossClient.doesObjectExist(bucketName, objectName);
        if (!isExist) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut("下载模版失败，当前省份没有配置模版");
        }
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, objectName);
        // 读取文件内容。
        try( BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent());
             BufferedOutputStream out = new BufferedOutputStream(os);)
        {
            byte[] buffer = new byte[1024];
            int lenght = 0;
            while ((lenght = in.read(buffer)) != -1) {
                out.write(buffer, 0, lenght);
            }
            out.flush();
        }
        catch (IOException e) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut(e.getMessage());
        }

    }

    /**
     * @desc 下载文件
     */
    @Override
    public InputStream exportOssFileStream(String objectName) throws IOException {
        // 创建OSSClient实例。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        conf.setSLDEnabled(true);
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, conf);
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, objectName);
        // 读取文件内容。
        return new BufferedInputStream(ossObject.getObjectContent());
    }
}
